//
//  YYGuideView.swift
//  CodeLibrary_Swift
//
//  Created by 陆文宇 on 2017/4/24.
//  Copyright © 2017年 陆文宇. All rights reserved.
//

import UIKit

protocol YYGuideViewDelegate: NSObjectProtocol {
    func clickInside(tag: Int) -> Void
    
    func canClickOutside() -> Bool
    func clickOutside() -> Void
}

extension YYGuideViewDelegate {
    func canClickOutside() -> Bool {
        return true
    }
    
    func clickOutside() -> Void {
        YYGuideView.dismissGuide()
    }
}

class YYGuideView: UIView {
    
    static let shared = YYGuideView()
    static var yyDelegate: YYGuideViewDelegate? {
        set {
            shared.yyDelegate = newValue
        }
        
        get {
            return shared.yyDelegate
        }
    }
    
    static var showFrame: CGRect {
        set {
            shared.path = UIBezierPath(rect: shared.frame)
            shared.path.append(UIBezierPath(roundedRect: newValue, cornerRadius: 5).reversing())
            shared.pathFrame = newValue
            
            let shapeLayer = CAShapeLayer()
            shapeLayer.path = shared.path.cgPath
            shared.layer.mask = shapeLayer
            
            let x = newValue.origin.x
            let y = newValue.origin.y
            let w = newValue.size.width
            let h = newValue.size.height
            let mX = x + w / 2
            let mY = y + h / 2
            
            var iX: CGFloat = 0
            var iY: CGFloat = 0
            var iW = shared.imageView.image!.size.width
            var iH = shared.imageView.image!.size.height
            let cW = mX / UIScreen.main.bounds.size.width < 0.5 ? UIScreen.main.bounds.size.width - x : x + w
            if iW > cW {
                iW = cW
                iH *= cW / iW
            }
            if mX / UIScreen.main.bounds.size.width < 0.5 {
                iX = x
            } else {
                iX = x + w - iW
            }
            if mY / UIScreen.main.bounds.size.height <= 0.5 {
                iY = y + h
            } else {
                iY = y - iH
            }
            
            let imageFrame = CGRect(x: iX, y: iY, width: iW, height: iH)
            
            shared.imageView.frame = imageFrame
        }
        
        get {
            return shared.pathFrame
        }
    }
    
    static func show(in frame: CGRect, guideImage: String, tag: Int) -> Void {
        shared.show(in: frame, guideImage: guideImage, tag: tag)
    }
    
    static func dismissGuide() -> Void {
        shared.dismissGuide()
    }
    
    var yyDelegate: YYGuideViewDelegate?
    var path: UIBezierPath!
    var pathFrame: CGRect!
    let imageView: UIImageView
    
    init() {
        imageView = UIImageView()
        super.init(frame: UIScreen.main.bounds)
        
        backgroundColor = UIColor.gray.withAlphaComponent(0.8)
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction(sender:)))
        addGestureRecognizer(tap)
        
        addSubview(imageView)
    }
    
    @objc func tapAction(sender: UITapGestureRecognizer) -> Void {
        let point = sender.location(in: sender.view)
        if pathFrame.contains(point) {
            yyDelegate?.clickInside(tag: tag)
        } else {
            if yyDelegate?.canClickOutside() ?? false {
                yyDelegate?.clickOutside()
            }
        }
    }
    
    func show(in frame: CGRect, guideImage: String, tag: Int) -> Void {
        guard !guideImage.isEmpty else {
            return
        }
        
        imageView.image = UIImage(named: guideImage)
        YYGuideView.showFrame = frame
        self.tag = tag
        if superview == nil {
            UIApplication.shared.keyWindow?.addSubview(self)
        }
    }
    
    func dismissGuide() -> Void {
        removeFromSuperview()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

}
